from typing import List

import requests
import xmltodict
from ninja import Router, Query
from ninja.pagination import paginate
from django.utils import timezone
from django.db.transaction import atomic

from apps.commom.order_response_schema import OrderInfoResponseSchema, VipOrderInfoResponseSchema
from apps.commom.order import OrderInfoSerializer, VipOrderInfoSerializer
from models.choices import WaterCardType, AfterSalesStatus
from utils.auth import AppletAuthBearer
from utils.decorators import handle_exception

from water_applets import settings
from wechatpy import WeChatPay

from apps.user_applets.order_info.schemas import CreateOrderInfoSchema, \
    AppletsOrderFiltersSchema, PayOrderByWaterSchema, OrderRefundSchema
from apps.schemas import R
from models.models import OrderInfo, VipOrderInfo, WaterDropletsRecord, WaterDropletsTask, WaterCardRecord
from utils.paginations import MyPagination
from utils.snowflake import snowflake

order_applet_router = Router(tags=["小程序订单"], auth=AppletAuthBearer())


@order_applet_router.post("/order", summary="创建订单")
@handle_exception("创建订单失败")
def create_order(request, data: CreateOrderInfoSchema):
    order_dict = data.dict()
    order_dict["order_id"] = snowflake()
    order_dict["user"] = request.user
    new_order = OrderInfo.objects.create(**order_dict)
    return R.ok(OrderInfoSerializer(new_order).data)


@order_applet_router.post("/{good_id}/vip_order", summary="创建VIP订单")
@handle_exception("创建VIP订单失败")
def create_vip_order(request, good_id):
    new_order = VipOrderInfo.objects.create(package_id=good_id, user=request.user)
    return R.ok(VipOrderInfoSerializer(new_order).data)


@order_applet_router.get("/orders", summary="获取订单列表", response=List[OrderInfoResponseSchema])
@handle_exception("获取订单列表失败")
@paginate(MyPagination)
def get_orders(request, filters: AppletsOrderFiltersSchema = Query(...)):
    orders = OrderInfo.objects.all()
    orders = filters.filter(orders)
    return orders


@order_applet_router.get("/order/{order_id}", summary="获取订单详情")
@handle_exception("获取订单详情失败")
def get_order(request, order_id: int):
    order = OrderInfo.objects.filter(order_id=order_id).first()
    if not order:
        return R.fail("订单不存在")
    return R.ok(OrderInfoSerializer(order).data)


@order_applet_router.get("/vip_orders", summary="获取VIP订单列表", response=List[VipOrderInfoResponseSchema])
@handle_exception("获取VIP订单列表失败")
@paginate(MyPagination)
def get_vip_orders(request, filters: AppletsOrderFiltersSchema = Query(...)):
    orders = VipOrderInfo.objects.all()
    orders = filters.filter(orders)
    return orders


@order_applet_router.get("/vip_order/{order_id}", summary="获取VIP订单详情")
@handle_exception("获取VIP订单详情失败")
def get_vip_order(request, order_id: str):
    order = VipOrderInfo.objects.filter(order_id=order_id).first()
    if not order:
        return R.fail("订单不存在")
    return R.ok(VipOrderInfoSerializer(order).data)


@order_applet_router.delete("/order/{order_id}", summary="删除订单")
@handle_exception("删除订单失败")
def delete_order(request, order_id: int):
    if not OrderInfo.objects.filter(order_id=order_id).exists():
        return R.fail("订单不存在")
    OrderInfo.objects.get(order_id=order_id).delete()
    return R.ok(msg="删除成功")


@order_applet_router.post("/order_refund", summary="普通订单申请退款")
@handle_exception("申请失败")
def order_refund(request, data: OrderRefundSchema):
    if len(data.reason) < 1 or len(data.reason) > 34:
        return R.fail(msg="退款原因长度必须在1-34个字符之间")
    if not OrderInfo.objects.filter(order_id=data.order_id, user=request.user).exists():
        return R.fail(msg="订单不存在")
    else:
        order = OrderInfo.objects.filter(order_id=data.order_id, user=request.user).first()
        order.after_sales_status = AfterSalesStatus.REFUND_IN_PROGRESS
        order.refund_reason = data.reason
        order.save()
        return R.ok(msg="申请成功")


@order_applet_router.post("/vip_order_refund", summary="VIP订单申请退款")
@handle_exception("申请失败")
def vip_order_refund(request, data: OrderRefundSchema):
    if len(data.reason) < 1 or len(data.reason) > 34:
        return R.fail(msg="退款原因长度必须在1-34个字符之间")
    if not VipOrderInfo.objects.filter(order_id=data.order_id, user=request.user).exists():
        return R.fail(msg="订单不存在")
    else:
        order = VipOrderInfo.objects.filter(order_id=data.order_id, user=request.user).first()
        order.after_sales_status = AfterSalesStatus.REFUND_IN_PROGRESS
        order.refund_reason = data.reason
        order.save()
        return R.ok(msg="申请成功")


@order_applet_router.delete("/vip_order/{order_id}", summary="删除VIP订单")
@handle_exception("删除VIP订单失败")
def delete_vip_order(request, order_id: str):
    if not VipOrderInfo.objects.filter(order_id=order_id).exists():
        return R.fail("订单不存在")
    VipOrderInfo.objects.get(order_id=order_id).delete()
    return R.ok(msg="删除成功")


@order_applet_router.post("/order_pay/by_water", summary="水滴或水卡支付")
@handle_exception("水滴或水卡支付失败")
def pay_by_water(request, data: PayOrderByWaterSchema):
    if data.water_type not in [1, 2]:
        return R.ok(msg="支付类型错误")
    if not OrderInfo.objects.filter(id=data.order_id).exists():
        return R.ok(msg="订单不存在")
    order = OrderInfo.objects.get(pk=data.order_id)
    if data.water_type == 1:
        if request.user.water_droplets_number < order.good_spec.water_droplets * order.good_number:
            return R.ok(msg="水滴不足")
        with atomic():
            order.user.water_drop_number -= order.good_spec.water_droplets * order.good_number
            order.user.save()
            order.transaction_status = 1
            order.consume_water_droplets = order.good_spec.water_droplets * order.good_number
            order.transaction_time = timezone.now()
            water_droplets_task = WaterDropletsTask.objects.get(pk=4)
            # 添加兑换商品的水滴增加记录
            WaterDropletsRecord.objects.create(user=request.user, op_type=WaterCardType.GET,
                                               task_name=water_droplets_task.task_name,
                                               droplet_number=WaterDropletsTask.objects.get(pk=4).droplet_number,
                                               op_time=timezone.now(),
                                               )
            # 添加兑换商品的水滴减少记录
            WaterDropletsRecord.objects.create(user=request.user,
                                               op_type=WaterCardType.CONSUME,
                                               task_name="兑换商品",
                                               droplet_number=order.good_spec.water_droplets * order.good_number,
                                               op_time=timezone.now(),
                                               )
            order.save()
            return R.ok(msg="支付成功")
    if data.water_type == 2:
        if request.user.water_card_number < order.good_spec.water_cards * order.good_number:
            return R.ok(msg="水卡不足")
        with atomic():
            order.user.water_card_number -= order.good_spec.water_cards * order.good_number
            order.user.save()
            order.transaction_status = 1
            order.consume_water_card = order.good_spec.water_cards * order.good_number
            order.transaction_time = timezone.now()
            WaterCardRecord.objects.create(user=request.user, card_type=WaterCardType.CONSUME,
                                           name="水卡使用",
                                           number=order.good_spec.water_cards * order.good_number,
                                           time=timezone.now(),
                                           )
            order.save()
            return R.ok(msg="支付成功")


@order_applet_router.get("/order/get_pay_id/{order_id}", summary="获取订单支付id")
@handle_exception("获取订单支付id失败")
def get_order_pay_id(request, order_id: str):
    notify_url = f"{settings.WEB_SERVER_IPV4}{+settings.WEB_SERVER_PORT}/applets/wx/order/payment/wxnotify"
    order = OrderInfo.objects.get(order_id=order_id)
    pay = WeChatPay(appid=settings.WECHAT_APPID,
                    api_key=settings.WECHAT_MERCHANT_KEY,
                    sub_appid=settings.WECHAT_APPID,
                    mch_id=settings.WECHAT_MERCHANT_ID)
    response = pay.order.create(trade_type="JSAPI",
                                body=order.good.describe,
                                out_trade_no=order.order_id,
                                user_id=request.user.openid,
                                total_fee=int(order.good_spec.price * order.good_number * 100),
                                notify_url=notify_url)
    if response["return_code"] == 'SUCCESS':
        # 获取预支付交易会话标识
        prepay_id = response.get("prepay_id")
        # 封装返回给前端的数据
        data = {"prepay_id": prepay_id, }
        order.transaction_id = prepay_id
        order.transaction_time = timezone.now()
        order.save()
        return R.ok(data)
    else:
        return R.fail("请求支付失败")


@order_applet_router.get("/vip_order/get_pay_id/{order_id}", summary="获取VIP订单支付id")
@handle_exception("获取订单支付id失败")
def get_vip_order_pay_id(request, order_id: str):
    notify_url = f"{settings.WEB_SERVER_IPV4}{+settings.WEB_SERVER_PORT}/applets/wx/vip_order/payment/wxnotify"
    order = VipOrderInfo.objects.get(order_id=order_id)
    pay = WeChatPay(appid=settings.WECHAT_APPID, api_key="", sub_appid="", mch_id=settings.WECHAT_MERCHANT_ID)
    response = pay.order.create(trade_type="JSAPI",
                                user_id=request.user.openid,
                                total_fee=order.package.price * 100,
                                notify_url=notify_url)
    content = xmltodict.parse(response.content)
    if content["return_code"] == 'SUCCESS':
        # 获取预支付交易会话标识
        prepay_id = content.get("prepay_id")
        # 封装返回给前端的数据
        data = {"prepay_id": prepay_id, }
        # order = await OrderInfo.objects.aget(order_id=request.GET.get("out_trade_no"))
        order.transaction_id = prepay_id
        order.transaction_time = timezone.now()
        order.save()
        return R.ok(data)
    else:
        return R.fail("请求支付失败")
